home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / System / XFD / Developer / Sources / ASM / KennyGrant.a < prev    next >
Encoding:
Text File  |  2001-09-16  |  18.5 KB  |  850 lines

  1. ; Grants Computing decrunchers
  2. ; by Kyzer/CSG & Kenny Grant
  3. ;
  4. ; 1.0:    works OK, could probably do with range checks on relocs and validity
  5. ;    checks on compressed data. syskiller GC!2 formats still todo
  6. ; 1.1:    now includes data slaves, but not GC!2 exe formats
  7. ;
  8. ; Kenny Grant compiled Amiga Power coverdisks for issues 20-43 and
  9. ; 50-55, he also did some stuff for CU Amiga. Read the story of the AP
  10. ; coverdisk at http://dspace.dial.pipex.com/ap2/comments/JN/disks.html
  11. ;
  12. ; Thanks to Mr.Larmer for writing the previous datafile-only slave, called
  13. ; 'GraftGold', however the decrunch code I first extracted from the example
  14. ; files exactly matched the graftgold slave, so technically I didn't need
  15. ; to refer to his slave...
  16.  
  17.     include    dos/doshunks.i
  18.     include    exec/memory.i
  19.     include    libraries/xfdmaster.i
  20.     include    lvo/exec_lib.i
  21.  
  22.     IFD    TEST
  23.     include    xfdExeHead.a
  24.     ENDC
  25.  
  26. ForeMan    dc.l    $70FF4E75,XFDF_ID    ; id
  27.     dc.w    XFDF_VERSION        ; foreman version
  28.     dcb.w    5,0            ; reserved stuff
  29. ;    dc.l    GC2exe            ; first slave
  30.     dc.l    GC2data            ; first slave
  31.  
  32.     dc.b    '$VER: KennyGrant 1.0 (22.01.2000) by <kyzer@4u.net>',0
  33. GC2exe_name    dc.b    'Grants Computing (GC!2)',0
  34. GC3exe_name    dc.b    'Grants Computing (GC!3)',0
  35. GC2data_name    dc.b    'Grants Computing (GC!2) Data',0
  36. GC3data_name    dc.b    'Grants Computing (GC!3) Data',0
  37.     cnop    0,4
  38.  
  39. GC2exe    dc.l    GC2data
  40.     dc.w    2,38
  41.     dc.l    GC2exe_name
  42.     dc.w    XFDPFF_ADDR,0
  43.     dc.l    GC2exe_recog,GC2exe_decrunch,0,0
  44.     dc.l    0,1024    ;******** Calculate this right!!
  45.  
  46. GC2data    dc.l    GC3exe
  47.     dc.w    2,39            ; slave v2+ requires master v39+
  48.     dc.l    GC2data_name
  49.     dc.w    XFDPFF_DATA!XFDPFF_RECOGLEN!XFDPFF_USERTARGET,0
  50.     dc.l    GC2data_recog,GC2data_decrunch,GC2data_scan,GC2data_verify
  51.     dc.l    0,18
  52.  
  53. GC3exe    dc.l    GC3data
  54.     dc.w    2,38
  55.     dc.l    GC3exe_name
  56.     dc.w    XFDPFF_RELOC,0
  57.     dc.l    GC3exe_recog,GC3exe_decrunch,0,0
  58.     dc.l    0,44+944
  59.  
  60. GC3data    dc.l    0
  61.     dc.w    2,39
  62.     dc.l    GC3data_name
  63.     dc.w    XFDPFF_DATA!XFDPFF_RECOGLEN!XFDPFF_USERTARGET,0
  64.     dc.l    GC3data_recog,GC3data_decrunch,GC3data_scan,GC3data_verify
  65.     dc.l    0,18
  66.  
  67.  
  68. ;****************************************************************************
  69. ;****************************************************************************
  70. ;****************************************************************************
  71. ;
  72. ; GC!2 and GC!3 crunched data format:
  73. ; longword ID: GC!\02 or GC!\03
  74. ; longword unpacked length
  75. ; longword packed length
  76. ; remainder is crunched stuff (6 bytes immediately & unconditionally read)
  77. ; total for minimum: 18 bytes
  78.  
  79.  
  80. GC2_ID    = ("G"<<24) + ("C"<<16) + ("!"<<8) + 2
  81. GC3_ID    = ("G"<<24) + ("C"<<16) + ("!"<<8) + 3
  82.  
  83. GC2data_recog
  84.     move.l    #GC2_ID,d0
  85.     bra.s    __recog
  86. GC3data_recog
  87.     move.l    #GC3_ID,d0
  88. __recog    cmp.l    (a0)+,d0
  89.     bne.s    .fail
  90.     move.l    (a0)+,d0        ; d0 = unpacked length
  91.     beq.s    .fail            ; fail if unpacked length = 0
  92.     move.l    (a0)+,d1        ; d1 = packed length
  93.     beq.s    .fail            ; fail if packed length = 0
  94.     cmp.l    d0,d1
  95.     bhi.s    .fail            ; fail if packed length > unpacked
  96.     move.l    d0,xfdrr_FinalTargetLen(a1)
  97.     add.l    #52,d0            ; safety for GC!2 (see GC2_DECRUNCH)
  98.     move.l    d0,xfdrr_MinTargetLen(a1)
  99.     moveq    #12,d0
  100.     add.l    d0,d1
  101.     move.l    d1,xfdrr_MinSourceLen(a1)
  102.     moveq    #1,d0            ; return success
  103.     rts
  104. .fail    moveq    #0,d0
  105.     rts
  106.  
  107. GC2data_decrunch
  108.     move.l    a2,-(sp)
  109.     lea    GC2_DECRUNCH(pc),a2
  110.     bra.s    __decr
  111. GC3data_decrunch
  112.     move.l    a2,-(sp)
  113.     lea    GC3_DECRUNCH(pc),a2
  114. __decr    move.l    xfdbi_UserTargetBuf(a0),a1
  115.     move.l    xfdbi_SourceBuffer(a0),a0
  116.     addq.l    #4,a0
  117.     jsr    (a2)
  118.     move.l    (sp)+,a2
  119.     rts
  120.  
  121. GC2data_scan
  122.     moveq   #0,d0
  123.     cmp.l   #GC2_ID,(a0)
  124.     bne.s    .fail
  125.     moveq    #1,d0
  126. .fail    rts
  127. GC3data_scan
  128.     moveq   #0,d0
  129.     cmp.l   #GC3_ID,(a0)
  130.     bne.s    .fail
  131.     moveq    #1,d0
  132. .fail    rts
  133.  
  134.  
  135. GC2data_verify
  136. GC3data_verify
  137.     moveq   #12,d1
  138.     add.l   8(a0),d1        ; d1 = packed length
  139.     cmp.l   d0,d1
  140.     bhi.s    .fail            ; fail if packed len > remaining len
  141.     cmp.l    4(a0),d1
  142.     bhi.s    .fail            ; fail if packed len > unpacked len
  143.     move.l    d1,d0
  144.     rts
  145. .fail    moveq    #0,d0
  146.     rts
  147.  
  148.  
  149.  
  150.  
  151. ;****************************************************************************
  152. ;****************************************************************************
  153. ;****************************************************************************
  154. ;
  155. ;Grants Computing (Kenny Grant) GC!2 syskiller format
  156.  
  157.  
  158. GC2exe_recog
  159.     moveq    #0,d0
  160.     rts
  161.  
  162. GC2exe_decrunch
  163.     moveq    #0,d0
  164.     rts
  165.  
  166.  
  167. ;Grants Computing (Kenny Grant) GC!3 overlay format
  168. ;
  169. ;Executable overlay header (a few changes to the code here and there),
  170. ;performs a SEEK call with an offset - matches with the first byte after
  171. ;the hunk_overlay header the real data starts there.
  172. ;
  173. ;(1) a longword listing the total number of hunks.
  174. ;
  175. ;(2) one longword for each hunk representing arguments to AllocMem():
  176. ;    - (upper 8 bits >>24)|MEMF_CLEAR -> lower 8 bits of D1
  177. ;    - lower 24 bits && $00FFFFFF -> D0
  178. ;
  179. ;(3) here begins a loop for each hunk in the decrunched file
  180. ;    - one longword that states what the hunk is:
  181. ;      944 & 932 BYTES VERSION
  182. ;      - longword < 0: throw away next longword, goto (3) ; 944 only?
  183. ;      - longword = 0: copy verbatim to fill the hunk, goto (4)
  184. ;      924 & 936 BYTES VERSION
  185. ;      - longword = 0: goto (3)
  186. ;      ALL VERSIONS
  187. ;      - longword  > 0: (always "GC!"<<8+3) if size!=0 decruncher; goto (4)
  188. ;
  189. ;(4) if longword >=0 (ie isn't BSS), there may be relocs
  190. ;    - standard reloc format (num, hunk, relocs[num], num...)
  191. ;    - if first num=0, there are no relocs
  192. ;
  193. ;Examples:
  194. ;944 byte ver: AP38a:AtomSmasher, AP39a:TrickorTreat, AP38a:VectorBattleGround
  195. ;936 byte ver: AP34a:SmidgeDemo, AP38a:SuperObliteration
  196. ;932 byte ver: AP37a:Monaco
  197. ;924 byte ver: AP35:Statix
  198.  
  199. GC3exe_recog
  200.     cmp.l    #HUNK_HEADER,(a0)    ; executable?
  201.     bne.s    .fail
  202.     cmp.w    #2,10(a0)        ; 2 hunks?
  203.     bne.s    .fail
  204.     lea    32(a0),a0
  205.     move.l    (a0)+,d0        ; a0 = start of code hunk
  206.     asl.l    #2,d0            ; d0 = size of code hunk
  207.     cmp.l    #944,d0
  208.     bhi.s    .fail            ; code size <= 944 bytes?
  209.     lea    (a0,d0.w),a1        ; a1 = end of code hunk
  210.     cmp.l    #HUNK_OVERLAY,4(a1)    ; hunk 2 = overlay?
  211.     bne.s    .fail
  212.  
  213.     cmp.w    #$6000,(a0)        ; check bra.w instruction
  214.     bne.s    .fail
  215.     addq.l    #2,a0
  216.     adda.w    (a0),a0            ; skip past overlay header
  217.  
  218.     ; check the code itself
  219.     cmp.l    #$4eadffc4,$18(a0)    ; check jsr _LVOOutput(a5)
  220.     bne.s    .fail
  221.     cmp.b    #$67,$1E(a0)        ; check for 944 byte version
  222.     bne.s    .not944            ; which has an extra instruction here
  223.     addq.l    #2,a0            ; compensate for extra instruction
  224. .not944    cmp.w    #$243A,$30(a0)        ; check for 936 byte version
  225.     bne.s    .not936            ; which has 'move.l xxx(pc),d2'
  226.     move.w    $32(a0),d1        ; d1 = xxxx
  227.     lea    $32(a0,d1.w),a1        ; a1 = xxxx(pc)
  228.     move.l    (a1),d1            ; d1 = offset
  229.     bra.s    .cont
  230. .not936    cmp.w    #$243C,$30(a0)        ; check for other versions
  231.     bne.s    .fail            ; which have 'move.l #offset,d2'
  232.     move.l    $32(a0),d1        ; d1 = offset
  233. .cont    add.l    #52,d0            ; check offset == (codesize+52)
  234.     cmp.l    d0,d1
  235.     bne.s    .fail
  236.  
  237.     moveq    #1,d0
  238.     rts
  239. .fail    moveq    #0,d0
  240.     rts
  241.  
  242.  
  243.     STRUCTURE myhunk,0
  244.     ULONG    h_len
  245.     APTR    h_addr
  246.     UBYTE    h_pad
  247.     UBYTE    h_memflags
  248.     UBYTE    h_isbss
  249.     UBYTE    h_ispacked
  250.     LABEL    h_SIZEOF
  251.  
  252. MAX_HUNKS=20    ; this is an arbitrary number
  253. hunks=-h_SIZEOF*MAX_HUNKS
  254.  
  255. GC3exe_decrunch
  256.     movem.l    d2-d7/a2-a6,-(sp)
  257.     link    a5,#hunks        ; a5 = hunks
  258.     move.l    a0,a4            ; a4 = BufferInfo
  259.  
  260.     move.w    #XFDERR_CORRUPTEDDATA,xfdbi_Error(a4)
  261.     move.l    xfdbi_SourceBuffer(a4),a3
  262.     move.l    a3,a0
  263.     lea    36(a3),a2        ; a2 = start of code (temp)
  264.     bsr    GC3exe_recog        ; d1 = offset of data
  265.     lea    (a3,d1.w),a3        ; a3 = start of data
  266.  
  267.  
  268.     ; A0=data_ptr A4=BufferInfo A5=hunks A6=current_hunk
  269.     ; D4=relocs_size D5=944style D6=current_hunk D7=number_hunks
  270.     ; A1/A2/A3/D0/D1/D2/D3/D4=scratch
  271.  
  272.  
  273.     ; check which version of code this file is
  274.     ; ('944 style' means code=0 for unpacked)
  275.     ; ('not 944 style' means code=0 for bss)
  276.     move.b    $fa(a2),d0
  277.  
  278.     moveq    #1,d5
  279.     cmp.b    #$6a,d0            ; 944 byte version (944style)
  280.     beq.s    .styled
  281.     cmp.b    #$22,d0            ; 932 byte version (944style)
  282.     beq.s    .styled
  283.  
  284.     moveq    #0,d5
  285.     cmp.b    #$53,d0            ; 936 byte version (not 944style)
  286.     beq.s    .styled
  287.     cmp.b    #$20,d0            ; 924 byte version (not 944style)
  288.     bne    .fail
  289. .styled
  290.  
  291.  
  292.     ; get the number of hunks
  293.     move.l    a3,a0            ; a0 = data_ptr
  294.     move.l    (a0)+,d7        ; d7 = number of hunks
  295.     cmp.l    #MAX_HUNKS,d7
  296.     bhi    .fail            ; fail if too many hunks for us
  297.  
  298.  
  299.     ; get the sizes/flags of hunks
  300.     lea    hunks(a5),a6        ; FOR all hunks
  301.     move.l    d7,d6
  302.  
  303. 01$    move.l    (a0)+,d0        ; read len/memflags
  304.     move.l    d0,d1
  305.     andi.l    #$ffffff,d0        ; extract length of hunk
  306.     move.l    d0,h_len(a6)        ; and store it
  307.     andi.w    #3,d0
  308.     bne    .fail            ; hunksize must be multiple of 4
  309.     rol.l    #8,d1            ; extract memflags of hunk
  310.     clr.l    h_pad(a6)        ; clear isbss/ispacked/memflags
  311.     move.b    d1,h_memflags(a6)    ; store memflags
  312.  
  313.     lea    h_SIZEOF(a6),a6        ; NEXT
  314.     subq    #1,d6
  315.     bne.s    01$
  316.  
  317.  
  318.     ; get types and relocs of hunks
  319.     moveq    #0,d4            ; d4 = size of relocs
  320.     lea    hunks(a5),a6        ; FOR all hunks
  321.     move.l    d7,d6
  322.  
  323. 11$    move.l    (a0)+,d0        ; read typeid
  324.     bne.s    .nzero            ; typeid=0 is ambiguous
  325.     tst.l    d5
  326.     bne.s    .israw            ; typeid=0 944style is raw data
  327. .isbss    st.b    h_isbss(a6)        ; typeid=0 !944style is bss
  328.     bra.s    12$
  329. .nzero    bpl.s    .ispack            ; typeid>0 is always packed data
  330.     tst.l    d5
  331.     beq    .fail            ; typeid<0 944style is bss
  332.     addq.l    #4,a0            ; 944style bss has extra long (why?)
  333.     bra.s    .isbss
  334.  
  335. .israw    move.l    a0,h_addr(a6)        ; remember where data is
  336.     add.l    h_len(a6),a0        ; skip to end of data
  337.     bra.s    .relocs            ; raw data can have relocs
  338.  
  339. .ispack    move.l    a0,h_addr(a6)        ; remember where data is
  340.     st.b    h_ispacked(a6)
  341.     tst.l    h_len(a6)
  342.     beq.s    .relocs            ; no data if hunk is empty
  343.     addq.l    #4,a0            ; skip unpacked size
  344.     add.l    (a0)+,a0        ; skip to end of packed data
  345. ;    bra.s    .relocs            ; packed data can have relocs
  346.  
  347. .relocs    move.l    a0,d1            ; d1 = start of relocs
  348.     move.l    (a0)+,d0        ; get number of relocs
  349.     beq.s    12$            ; finish if relocs=0
  350.     addq.l    #4,d4            ; add hunk_reloc id to reloc size
  351. 13$    asl.l    #2,d0
  352.     lea    4(a0,d0.w),a0        ; skip to more relocs or end
  353.     move.l    (a0)+,d0        ; if there are more relocs, go back
  354.     bne.s    13$
  355.     move.l    a0,d0
  356.     sub.l    d1,d0            ; d0 = size of relocs (end-start)
  357.     add.l    d0,d4            ; add to reloc size
  358.  
  359. 12$    lea    h_SIZEOF(a6),a6        ; NEXT hunk
  360.     subq    #1,d6
  361.     bne.s    11$
  362.  
  363.     ; calculate size of output executable
  364.     ; = (4*5)            hunk_header,0,n,0,n-1
  365.     ; + 4*4*numhunks        sizeinhdr,hunkid,hunksize,hunk_end
  366.     ; + relocs
  367.  
  368.     moveq    #4*5,d0    ; 4*5
  369.     move.l    d7,d1
  370.     asl.l    #4,d1
  371.     add.l    d1,d0    ; + 4*4*number_of_hunks
  372.     add.l    d4,d0    ; + size of relocs
  373.  
  374.     ; sum non-BSS hunk sizes
  375.     lea    hunks(a5),a6        ; FOR all hunks
  376.     move.l    d7,d6
  377. 21$    tst.b    h_isbss(a6)        ; if hunk isn't bss
  378.     bne.s    .izbss
  379.     add.l    h_len(a6),d0        ; add its value to the total
  380. .izbss    lea    h_SIZEOF(a6),a6        ; NEXT
  381.     subq    #1,d6
  382.     bne.s    21$
  383.  
  384.     ; d0 = calculated size
  385.  
  386.     ; allocate memory
  387.     move.w    #XFDERR_NOMEMORY,xfdbi_Error(a4)
  388.     move.l    d0,xfdbi_TargetBufLen(a4)
  389.     move.l    d0,xfdbi_TargetBufSaveLen(a4)
  390.     move.l    xfdbi_TargetBufMemType(a4),d1
  391.     move.l    4.w,a6
  392.     jsr    _LVOAllocMem(a6)
  393.     move.l    d0,xfdbi_TargetBuffer(a4)
  394.     beq    .fail
  395.     move.l    d0,a1            ; a1 = output
  396.  
  397.  
  398.     ; A0/A3/A4/A6=scratch A1=output A5=hunks A6=current_hunk
  399.     ; D0/D1/D2/D3/D4/D5=scratch D6=current_hunk D7=number_hunks
  400.  
  401.     ; write hunk header
  402.     move.l    #HUNK_HEADER,(a1)+    ; write header
  403.     clr.l    (a1)+            ; write name (null)
  404.     move.l    d7,d0
  405.     move.l    d0,(a1)+        ; write num_hunks
  406.     clr.l    (a1)+            ; write first hunk (0)
  407.     subq    #1,d0
  408.     move.l    d0,(a1)+        ; write last hunk (num_hunks-1)
  409.     lea    hunks(a5),a6
  410. 31$    move.l    h_len(a6),d1        ; get length
  411.     asr.l    #2,d1            ; bytes->longwords
  412.  
  413.     btst.b    #MEMB_CHIP,h_memflags(a6)
  414.     beq.s    .nochip
  415.     bset    #30,d1            ; set 'chip mem' flag if needed
  416.     bra.s    .nofast
  417. .nochip    btst.b    #MEMB_FAST,h_memflags(a6)
  418.     beq.s    .nofast
  419.     bset    #31,d1            ; set 'fast mem' flag if needed
  420. .nofast
  421.     move.l    d1,(a1)+        ; write hunk length
  422.     lea    h_SIZEOF(a6),a6
  423.     dbra    d0,31$
  424.  
  425.  
  426.     ; write hunks
  427.     move.l    d7,d6            ; FOR all hunks
  428.     lea    hunks(a5),a6
  429.  
  430. 32$    move.l    h_len(a6),d0        ; get length
  431.     asr.l    #2,d0            ; bytes->longwords
  432.     tst.b    h_isbss(a6)
  433.     beq.s    .nobss
  434.     move.l    #HUNK_BSS,(a1)+        ; BSS hunk is just header
  435.     move.l    d0,(a1)+        ; and length
  436.     bra.s    .h_end
  437.  
  438. .nobss    move.l    #HUNK_CODE,(a1)+    ; data hunks are header
  439.     move.l    d0,(a1)+        ; length, and contents
  440.  
  441.     move.l    h_addr(a6),a0        ; get address of data
  442.     tst.b    h_ispacked(a6)
  443.     beq.s    .raw
  444.     tst.l    h_len(a6)        ; skip onwards if no data
  445.     beq.s    .reloc
  446.     bsr.s    GC3_DECRUNCH        ; otherwise decrunch from a0 to a1
  447.     addq.l    #4,a0            ; skip past crunched data
  448.     add.l    (a0)+,a0        ; so a0 points at relocs
  449.     add.l    h_len(a6),a1        ; advance output ptr
  450.     bra.s    .reloc
  451.  
  452. .raw    move.l    (a0)+,(a1)+        ; raw is just copy
  453.     subq.l    #1,d0            ; use length as num of longs to copy
  454.     bne.s    .raw            ; a0 is left pointing at relocs
  455.  
  456.     ; write relocs if need be
  457. .reloc    move.l    (a0)+,d0        ; get number of relocs
  458.     beq.s    .h_end            ; finish hunk if none
  459.     move.l    #HUNK_RELOC32,(a1)+    ; otherwise write reloc id
  460. 33$    move.l    d0,(a1)+        ; write number of relocs
  461.     move.l    (a0)+,(a1)+        ; write reloc hunk
  462. 34$    move.l    (a0)+,(a1)+
  463.     subq    #1,d0            ; LOOP for number of relocs
  464.     bne.s    34$
  465.     move.l    (a0)+,d0        ; if there are more relocs
  466.     bne.s    33$            ; go do them
  467.     move.l    #0,(a1)+        ; terminate reloc list
  468.  
  469. .h_end    move.l    #HUNK_END,(a1)+        ; write hunk_end id
  470.     lea    h_SIZEOF(a6),a6        ; NEXT hunk
  471.     subq    #1,d6
  472.     bne.s    32$
  473.  
  474.     ; success
  475.     clr.w    xfdbi_Error(a4)
  476.     moveq    #1,d0
  477.     bra.s    .done
  478. .fail    moveq    #0,d0
  479. .done    unlk    a5
  480.     movem.l    (sp)+,d2-d7/a2-a6
  481.     rts
  482.  
  483.  
  484. ;****************************************************************************
  485. ;****************************************************************************
  486. ;****************************************************************************
  487. ;
  488. ; GC!3 decruncher: A0=source (after header), A1=dest
  489.  
  490. GC3_DECRUNCH
  491.     movem.l    d0-d7/a0-a6,-(sp)
  492.     lea    -$620(sp),sp
  493.     move.l    (a0)+,d1        ; d1 = unpacked length
  494.     lea    0(a1,d1.l),a1        ; a1 = end of destination buffer
  495.     move.l    (a0)+,d2        ; d2 = packed length
  496.  
  497. ;    move.l    a0,d0            ; this bit of code arranges that
  498. ;    add.l    d2,d0            ; the 5kb read buffer which is
  499. ;    sub.l    DATA_BUFFER(pc),d0    ; indexed by a0 is left pointing
  500. ;    divu.w    #5120,d0        ; at the right address after this
  501. ;    clr.w    d0            ; routine finishes - of course,
  502. ;    swap    d0            ; there's no 5kb buffer in the
  503. ;    add.l    DATA_BUFFER(pc),d0    ; the slave, so just take it
  504. ;    move.l    d0,$640(sp)        ; out
  505.  
  506.     lea    $20(sp),a6
  507.     move.w    (a0)+,d0
  508.     move.l    (a0)+,d6
  509.     moveq    #$10,d7
  510.     sub.w    d0,d7
  511.     lsr.l    d7,d6
  512.     move.w    d0,d7
  513.     moveq    #$10,d3
  514. 1$    lea    (sp),a2
  515.     bsr.l    12$
  516.     moveq    #$10,d1
  517.     bsr.l    10$
  518.     move.w    d0,d5
  519.     lea    $9E(a6),a2
  520.     lea    -$1E(a2),a5
  521. 2$    movea.l    a6,a4
  522.     bsr.s    6$
  523.     btst    #8,d0
  524.     bne.s    5$
  525.     move.w    d0,d4
  526.     lea    $20(a6),a4
  527.     exg    a5,a2
  528.     bsr.s    6$
  529.     exg    a5,a2
  530.     move.w    d0,d1
  531.     move.w    d0,d2
  532.     bne.s    3$
  533.     moveq    #1,d1
  534.     moveq    #$10,d2
  535. 3$    bsr.l    10$
  536.     bset    d2,d0
  537.     lea    1(a1,d0.w),a3
  538. 4$    move.b    -(a3),-(a1)
  539.     subq.w    #1,d4
  540.     bpl.s    4$
  541.     move.b    -(a3),-(a1)
  542.     move.b    -(a3),d0
  543. 5$    move.b    d0,-(a1)
  544.     subq.w    #1,d5
  545.     bpl.s    2$
  546.     moveq    #1,d1
  547.     bsr.s    10$
  548.     bne.s    1$
  549.     lea    $620(sp),sp
  550.     movem.l    (sp)+,d0-d7/a0-a6
  551.     rts
  552.  
  553. 6$    moveq    #0,d1
  554. 7$    subq.w    #1,d7
  555.     beq.s    8$
  556.     lsr.l    #1,d6
  557.     bra.s    9$
  558.  
  559. 8$    moveq    #$10,d7
  560.     move.w    d6,d0
  561.     lsr.l    #1,d6
  562.     swap    d6
  563.     move.w    (a0)+,d6
  564.     swap    d6
  565.     lsr.w    #1,d0
  566. 9$    addx.w    d1,d1
  567.     move.w    (a4)+,d0
  568.     cmp.w    d1,d0
  569.     bls.s    7$
  570.     add.w    $3E(a4),d1
  571.     add.w    d1,d1
  572.     move.w    0(a2,d1.w),d0
  573.     rts
  574.  
  575. 10$    move.w    d6,d0
  576.     lsr.l    d1,d6
  577.     sub.w    d1,d7
  578.     bgt.s    11$
  579.     add.w    d3,d7
  580.     ror.l    d7,d6
  581.     move.w    (a0)+,d6
  582.     rol.l    d7,d6
  583. 11$    move.l    d2,-(sp)
  584.     moveq    #1,d2
  585.     lsl.l    d1,d2
  586.     subq.l    #1,d2
  587.     move.l    d2,d1
  588.     move.l    (sp)+,d2
  589.     and.w    d1,d0
  590.     rts
  591.  
  592. 12$    moveq    #9,d2
  593.     lea    $9E(a6),a4
  594.     lea    -2(a6),a5
  595.     bsr.s    13$
  596.     moveq    #4,d2
  597.     lea    $80(a6),a4
  598.     lea    $1E(a6),a5
  599. 13$    movem.l    d2-d5/a1/a2,-(sp)
  600.     moveq    #4,d1
  601.     bsr.s    10$
  602.     moveq    #15,d5
  603.     sub.w    d0,d5
  604.     movea.w    d5,a1
  605.     suba.l    a3,a3
  606.     moveq    #0,d4
  607.     move.w    d0,d5
  608. 14$    addq.w    #1,d4
  609.     move.w    d4,d1
  610.     cmp.w    d2,d1
  611.     ble.s    15$
  612.     move.w    d2,d1
  613. 15$    bsr.s    10$
  614.     move.w    d0,(a2)+
  615.     adda.w    d0,a3
  616.     subq.w    #1,d5
  617.     bne.s    14$
  618.     move.w    a1,d5
  619. 16$    beq.s    17$
  620.     clr.w    (a2)+
  621.     subq.w    #1,d5
  622.     bra.s    16$
  623.  
  624. 17$    move.w    a3,d5
  625. 18$    move.w    d2,d1
  626.     bsr.s    10$
  627.     move.w    d0,(a4)+
  628.     subq.w    #1,d5
  629.     bne.s    18$
  630.     movem.l    (sp)+,d2-d5/a1/a2
  631.     movem.l    d2-d7/a2,-(sp)
  632.     clr.w    (a5)+
  633.     moveq    #0,d2
  634.     moveq    #0,d3
  635.     moveq    #-1,d4
  636.     moveq    #15,d7
  637. 19$    move.w    (a2)+,d6
  638.     move.w    d3,$40(a5)
  639.     move.w    -2(a5),d0
  640.     add.w    d0,d0
  641.     sub.w    d0,$40(a5)
  642.     add.w    d6,d3
  643.     add.w    d6,d2
  644.     move.w    d2,(a5)+
  645.     lsl.w    #1,d2
  646.     subq.l    #1,d7
  647.     bne.s    19$
  648.     movem.l    (sp)+,d2-d7/a2
  649.     rts
  650.  
  651.  
  652.  
  653. ;****************************************************************************
  654. ;****************************************************************************
  655. ;****************************************************************************
  656. ;
  657. ; GC!2 decruncher: A0=source (after header), A1=dest
  658.  
  659. GC2_DECRUNCH
  660.     movem.l    d0-d7/a0-a6,-(sp)
  661.     lea    -$454(sp),sp
  662. ;    cmpi.l    #$47432102,(a0)+
  663. ;    bne.l    9$
  664.  
  665.     move.l    (a0)+,d1        ; d1 = unpacked length
  666.     lea    0(a1,d1.l),a1        ; a1 = end of destination buffer
  667.  
  668.     ; heres a funny bit of code, that
  669.     ; seems to 'save' the 52 bytes after
  670.     ; the end of the decrunch buffer -
  671.     ; does it overwrite it in the routine?
  672.     moveq    #52,d0
  673.     lea    0(sp,d0.w),a2
  674. 1$    move.b    (a1)+,-(a2)
  675.     subq.l    #1,d0
  676.     bne.s    1$
  677.  
  678.     move.l    (a0)+,d2        ; d2 = packed length
  679.     adda.l    d2,a0            ; a0 = end of source buffer
  680.     lea    $54(sp),a6
  681.     move.w    -(a0),d0
  682.     move.l    -(a0),d6
  683.     moveq    #$10,d7
  684.     sub.w    d0,d7
  685.     lsr.l    d7,d6
  686.     move.w    d0,d7
  687.     moveq    #$10,d3
  688. 2$    lea    $34(sp),a2
  689.     bsr.l    16$
  690.     moveq    #$10,d1
  691.     bsr.l    14$
  692.     move.w    d0,d5
  693.     lea    $9E(a6),a2
  694.     lea    -$1E(a2),a5
  695. 3$
  696.  
  697. ;    move.l    a6,-(sp)
  698. ;    lea    COLOUR1_DATA(pc),a6    ; write colour into copperlist
  699. ;    move.w    d6,(a6)            ; to show decrunching
  700. ;    movea.l    (sp)+,a6
  701.  
  702.     movea.l    a6,a4
  703.     bsr.s    10$
  704.     btst    #8,d0
  705.     bne.s    6$
  706.     move.w    d0,d4
  707.     lea    $20(a6),a4
  708.     exg    a5,a2
  709.     bsr.s    10$
  710.     exg    a5,a2
  711.     move.w    d0,d1
  712.     move.w    d0,d2
  713.     bne.s    4$
  714.     moveq    #1,d1
  715.     moveq    #$10,d2
  716. 4$    bsr.s    14$
  717.     bset    d2,d0
  718.     lea    1(a1,d0.w),a3
  719. 5$    move.b    -(a3),-(a1)
  720.     subq.w    #1,d4
  721.     bpl.s    5$
  722.     move.b    -(a3),-(a1)
  723.     move.b    -(a3),d0
  724. 6$    move.b    d0,-(a1)
  725.     subq.w    #1,d5
  726.     bpl.s    3$
  727.     moveq    #1,d1
  728.     bsr.s    14$
  729.     bne.s    2$
  730.     move.l    -(a0),d0
  731.     divu.w    #$34,d0
  732.     addq.w    #1,d0
  733. 7$    movem.l    (a1),d1-d7/a0/a2-a6
  734.     movem.l    d1-d7/a0/a2-a6,-(a1)
  735.     lea    $68(a1),a1
  736.     subq.w    #1,d0
  737.     bne.s    7$
  738.  
  739.     ; and here it is again to restore?
  740.     swap    d0
  741.     moveq    #52,d1
  742.     suba.l    d1,a1
  743.     adda.l    d0,a1
  744.     lea    (sp),a0
  745. 8$    move.b    (a0)+,-(a1)
  746.     subq.l    #1,d1
  747.     bne.s    8$
  748.  
  749. 9$    lea    $454(sp),sp
  750.     movem.l    (sp)+,d0-d7/a0-a6
  751.     rts
  752.  
  753. 10$    moveq    #0,d1
  754. 11$    subq.w    #1,d7
  755.     beq.s    12$
  756.     lsr.l    #1,d6
  757.     bra.s    13$
  758.  
  759. 12$    moveq    #$10,d7
  760.     move.w    d6,d0
  761.     lsr.l    #1,d6
  762.     swap    d6
  763.     move.w    -(a0),d6
  764.     swap    d6
  765.     lsr.w    #1,d0
  766. 13$    addx.w    d1,d1
  767.     move.w    (a4)+,d0
  768.     cmp.w    d1,d0
  769.     bls.s    11$
  770.     add.w    $3E(a4),d1
  771.     add.w    d1,d1
  772.     move.w    0(a2,d1.w),d0
  773.     rts
  774.  
  775. 14$    move.w    d6,d0
  776.     lsr.l    d1,d6
  777.     sub.w    d1,d7
  778.     bgt.s    15$
  779.     add.w    d3,d7
  780.     ror.l    d7,d6
  781.     move.w    -(a0),d6
  782.     rol.l    d7,d6
  783. 15$    move.l    d2,-(sp)
  784.     moveq    #1,d2
  785.     lsl.l    d1,d2
  786.     subq.l    #1,d2
  787.     move.l    d2,d1
  788.     move.l    (sp)+,d2
  789.     and.w    d1,d0
  790.     rts
  791.  
  792. 16$    moveq    #9,d2
  793.     lea    $9E(a6),a4
  794.     lea    -2(a6),a5
  795.     bsr.s    17$
  796.     moveq    #4,d2
  797.     lea    $80(a6),a4
  798.     lea    $1E(a6),a5
  799. 17$    movem.l    d2-d5/a1/a2,-(sp)
  800.     moveq    #4,d1
  801.     bsr.s    14$
  802.     moveq    #15,d5
  803.     sub.w    d0,d5
  804.     movea.w    d5,a1
  805.     suba.l    a3,a3
  806.     moveq    #0,d4
  807.     move.w    d0,d5
  808. 18$    addq.w    #1,d4
  809.     move.w    d4,d1
  810.     cmp.w    d2,d1
  811.     ble.s    19$
  812.     move.w    d2,d1
  813. 19$    bsr.s    14$
  814.     move.w    d0,(a2)+
  815.     adda.w    d0,a3
  816.     subq.w    #1,d5
  817.     bne.s    18$
  818.     move.w    a1,d5
  819. 20$    beq.s    21$
  820.     clr.w    (a2)+
  821.     subq.w    #1,d5
  822.     bra.s    20$
  823.  
  824. 21$    move.w    a3,d5
  825. 22$    move.w    d2,d1
  826.     bsr.s    14$
  827.     move.w    d0,(a4)+
  828.     subq.w    #1,d5
  829.     bne.s    22$
  830.     movem.l    (sp)+,d2-d5/a1/a2
  831.     movem.l    d2-d7/a2,-(sp)
  832.     clr.w    (a5)+
  833.     moveq    #0,d2
  834.     moveq    #0,d3
  835.     moveq    #-1,d4
  836.     moveq    #15,d7
  837. 23$    move.w    (a2)+,d6
  838.     move.w    d3,$40(a5)
  839.     move.w    -2(a5),d0
  840.     add.w    d0,d0
  841.     sub.w    d0,$40(a5)
  842.     add.w    d6,d3
  843.     add.w    d6,d2
  844.     move.w    d2,(a5)+
  845.     lsl.w    #1,d2
  846.     subq.l    #1,d7
  847.     bne.s    23$
  848.     movem.l    (sp)+,d2-d7/a2
  849.     rts
  850.